package org.example.config;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;

@Configuration
public class RedisConfig {

    //这是一个 Spring Bean 的配置方法，会创建一个 RedisTemplate 实例
    //这个 RedisTemplate 的 key 是 String 类型，value 是 Object 类型
    //它接收一个 RedisConnectionFactory 参数，这是 Redis 连接的基础配置
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
//        创建 RedisTemplate 对象
//        设置 Redis 连接工厂
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // 1. 创建 ObjectMapper 并配置
        ObjectMapper mapper = new ObjectMapper();    //创建 Jackson 的 ObjectMapper 对象
        mapper.registerModule(new JavaTimeModule()); // 支持 Java 8 时间类型
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);        //禁用日期作为时间戳的写法（使用可读的字符串格式）
        mapper.activateDefaultTyping( // 类型安全支持（谨慎使用）
                LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL,
                JsonTypeInfo.As.PROPERTY
        );        //激活默认类型信息，以便反序列化时能正确处理多态类型


        // 2. 通过构造函数注入 ObjectMapper
        //使用配置好的 ObjectMapper 创建一个 JSON 序列化器
        //这个序列化器可以处理任意 Java 对象（Object.class）
        Jackson2JsonRedisSerializer<Object> serializer =
                new Jackson2JsonRedisSerializer<>(mapper, Object.class);

        // 3. 配置序列化方式
        //Key 和 HashKey 使用字符串序列化
        //Value 和 HashValue 使用上面配置的 JSON 序列化器
        template.setKeySerializer(RedisSerializer.string());
        template.setValueSerializer(serializer);
        template.setHashKeySerializer(RedisSerializer.string());
        template.setHashValueSerializer(serializer);

        return template;
    }
    
}